package com.example.demo.config.shiro;

import com.example.demo.dao.UserDao;
import com.example.demo.enums.UserStatus;
import com.example.demo.model.User;
import com.example.demo.util.PasswordUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.log4j.Logger;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.apache.shiro.util.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * shiro的认证最终是交给了Realm进行执行
 * 所以我们需要自己重新实现一个Realm，此Realm继承AuthorizingRealm
 * Created by sun on 2017-4-2.
 */
@Slf4j
public class WebShiroRealm extends AuthorizingRealm {

//    private static final MyPermissionResolver resolver = new MyPermissionResolver();
    private static final Logger logger = Logger.getLogger(WebShiroRealm.class);

//    @Autowired
//    private PermissionService permissionService;

    @Autowired
    private UserDao userDao;


    public WebShiroRealm() {
        super();
//        this.setPermissionResolver(resolver);
    }

    public boolean supports(AuthenticationToken token) {
        // 判断token类型，适用返回true，不适用返回false
        return true;
    }
    /**
     * 权限认证（为当前登录的Subject授予角色和权限）
     *
     * 该方法的调用时机为需授权资源被访问时，并且每次访问需授权资源都会执行该方法中的逻辑，这表明本例中并未启用AuthorizationCache，
     * 如果连续访问同一个URL（比如刷新），该方法不会被重复调用，Shiro有一个时间间隔（也就是cache时间，在ehcache-shiro.xml中配置），
     * 超过这个时间间隔再刷新页面，该方法会被执行
     *
     * doGetAuthorizationInfo()是权限控制，
     * 当访问到页面的时候，使用了相应的注解或者shiro标签才会执行此方法否则不会执行，
     * 所以如果只是简单的身份认证没有权限的控制的话，那么这个方法可以不进行实现，直接返回null即可
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//        String loginName = (String) super.getAvailablePrincipal(principals);
//        User user = permissionService.findByUserEmail(loginName);
//        logger.info("权限认证!");
//        if (user != null){
//            // 权限信息对象info，用来存放查出的用户的所有的角色及权限
//            SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//            //用户的角色集合
//            authorizationInfo.setRoles(permissionService.getRolesName(user.getId()));
//            List<Role> roleList = permissionService.getRoleList(user.getId());
//            for (Role role : roleList){
//                //用户的角色对应的所有权限
//                logger.info("角色: "+role.getName());
//                authorizationInfo.addStringPermissions(permissionService.getPermissionsName(role.getId()));
//            }
//            return authorizationInfo;
//        }
//        // 返回null将会导致用户访问任何被拦截的请求时都会自动跳转到 unauthorizedUrl 指定的地址
        return null;
    }

    /**
     * 登录认证
     *
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//        String username = (String)authenticationToken.getPrincipal();  //得到用户名
//        String password = new String((char[])authenticationToken.getCredentials()); //得到密码

        // UsernamePasswordToken用于存放提交的登录信息
        UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
        log.info("登录认证! 验证当前Subject时获取到token为:{}.",
                ReflectionToStringBuilder.toString(token, ToStringStyle.MULTI_LINE_STYLE));

        Map<String, String> criteria = new HashMap<>();
        criteria.put("username", String.valueOf(token.getPassword()));
        List<User> list = userDao.list(criteria);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        } else {
            User user = list.get(0);
            if(user.getStatus() == UserStatus.DISABLED.value()){
                throw new DisabledAccountException();
            }

            if (PasswordUtil.matches(token.getUsername(), user.getEncryptPassword(), PasswordUtil.salt)) {
                return new SimpleAuthenticationInfo(user, user.getUsername(), getName());
            } else {
                return null;
            }
//            if (StringUtils.isEmpty(user.getEncryptPassword())) {
//                PasswordUtil.encryptPassword(user, user.getSalt());
//            }

            // ByteSource salt = ByteSource.Util.bytes(user.getSalt());
            // 若存在，将此用户存放到登录认证info中，无需自己做密码对比，Shiro会为我们进行密码对比校验
//            return new SimpleAuthenticationInfo(user.getUsername(), user.getEncryptPassword(), getName());
        }

    }

}
